<?php

namespace App\Kuafu\Order\Service;


use App\Kuafu\Category\Model\CategoryModel;
use App\Kuafu\Order\Enum\CodeEnum;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Service\PayService;
use App\Library\SnowFlake\SnowFlake;

/**
 * 订单离线操作服务
 * Class OrderOperateService
 * @package App\Kuafu\Order\Service
 */
class OrderOfflineService extends OrderBaseSplitService
{
    /**
     * @var array 分类数据
     */
    public static array $categoryList = [];

    /**
     * 校验金额是否正确
     *
     * @param $data
     */
    public static function checkDataInputData($data): bool
    {
        // 判断 1. 原价 - 优惠 == 实付
        $orderOriginPrice   = $data['totalPrice']['originalPrice'];
        $orderDiscountPrice = $data['totalPrice']['discountPrice'];
        $orderPayPrice      = $data['totalPrice']['payPrice'];

        if ($orderOriginPrice - $orderDiscountPrice != $orderPayPrice) {
            return false;
        }
        // 判断 2. 原价是否相同
        $dishOriginPrice = 0;
        foreach ($data['detail'] as $dish) {
            $dishOriginPrice += $dish['originalPrice'];
        }

        if ($dishOriginPrice != $orderOriginPrice) {
            return false;
        }

        return true;
    }

    /**
     * 格式化离线 Order 入参数据
     *
     * @param $data
     */
    public static function formatOfflineOrderInputData($data)
    {
        $order['orderId']          = SnowFlake::nextIdCache();
        $order['brandId']          = $data['brandId'];
        $order['shopId']           = $data['shopId'];
        $order['sourceType']       = $data['sourceType'];
        $order['serialNum']        = $data['serialNum'];
        $order['offOrderId']       = $data['orderId']; // 离线订单号
        $order['userId']           = 0;
        $order['shouldPrice']      = 0; //剩余应付
        $order['orderShouldPrice'] = $data['totalPrice']['shouldPrice']; // 订单总应付
        $order['originalPrice']    = $data['totalPrice']['originalPrice'];
        $order['discountPrice']    = $data['totalPrice']['discountPrice'] ?? 0;
        $order['payPrice']         = $data['totalPrice']['payPrice'];
        $order['couponPrice']      = 0;
        $order['couponCostPrice']  = 0;
        $order['updatedAt']        = $data['createdAt'] ?? 0;
        $order['updatedByUid']     = $data['createdByUid'] ?? 0;
        $order['updatedBy']        = $data['createdBy'] ?? 0;
        $order['createdAt']        = $data['createdAt'] ?? 0;
        $order['createdByUid']     = $data['createdByUid'] ?? 0;
        $order['createdBy']        = $data['createdBy'] ?? 0;
        $order['remark']           = $data['remark'] ?? '';
        $order['refundMoney']      = $data['refundMoney'] ?? 0;
        $order['completeTime']     = $data['completeTime'] ?? 0;
        $order['refundStatus']     = $data['refundStatus'] ?? 0;
        $order['payChannel']       = $data['payMethod'] ?? 0;
        $order['isOffline']        = CodeEnum::ORDER_IS_ONLINE_OFFLINE;
        $order['payStatus']        = 1;
        $order['orderStatus']      = CodeEnum::ORDER_STATUS_FINISHED;

        // 判断是否是 试吃
        if ($order['payChannel'] == CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK) {
            $order['payPrice']      = 0;
            $order['discountPrice'] = $order['originalPrice'];
            $order['payChannel']    = CodeEnum::ORDER_PAY_CHANNEL_ZERO_PAY;
        }

        $order['realPayPrice']      = $order['payPrice'];
        $order['realDiscountPrice'] = $order['discountPrice'] ?? 0;

        return $order;
    }

    /**
     * 获取所有菜品分类数据
     *
     * @param $menuId
     */
    public static function setAllCategoryWithDel($menuId): void
    {
        if (empty(self::$categoryList[$menuId])) {
            $categoryList = CategoryModel::query()->where('menuId', $menuId)
                                         ->withoutGlobalScope('isDel')
                                         ->select('id', 'pid', 'name')
                                         ->get()
                                         ->keyBy('id')
                                         ->toArray();

            self::$categoryList[$menuId] = $categoryList;
        }
    }

    /**
     * 获取分类名称
     *
     * @param $id
     * @param $menuId
     * @return string
     */
    public static function getCategoryNameById($id, $menuId): string
    {
        return self::$categoryList[$menuId][$id]['name'] ?? '';
    }

    /**
     * 格式化 OrderDetail 入参数据
     *
     * @param $data
     * @return array
     */
    public static function formatOfflineOrderDetailInputData($data): array
    {
        $orderDetail = [];
        $allDiscount = $data['totalPrice']['discountPrice']; // 所有的优惠金额
        foreach ($data['detail'] as $detail) {
            $detail['id']    = SnowFlake::nextIdCache();
            $orderDetailList = self::formatOfflineOrderDetail($detail, $data);

            foreach ($detail['packageList'] as $packageOne) {
                $packageOne['id']                 = SnowFlake::nextIdCache();
                $orderDetailList['packageList'][] = self::formatOfflineOrderDetail($packageOne, $orderDetailList,
                    true);
            }

            if ($detail['freeNum'] > 0) {
                $orderDetailList['skipDiscount'] = true;

                $allDiscount -= $detail['originalPrice'];
            }

            $orderDetail[] = $orderDetailList;
        }

        // 过滤 跳过优惠的计算
        $skipForeach = [
            'skipDiscount' => []
        ];


        foreach ($orderDetail as $dKey => $detail) {
            foreach ($skipForeach as $key => &$v) {
                if (!empty($detail[$key]) && $detail[$key]) {
                    $v[] = $detail;
                    unset($orderDetail[$dKey]);
                }
            }
        }

        // 判断是否是 试吃
        if ($data['payMethod'] != CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK) {
            // 处理平均值
            $orderDetail = self::avgCalcPrice($orderDetail, 'originalPrice', [
                'payPrice' => $data['totalPrice']['payPrice']
            ]);
        }

        // 补回 数组
        foreach ($skipForeach as $skipData) {
            foreach ($skipData as $key => $skipDatum) {
                array_splice($orderDetail, $key + 1, 0, [$skipDatum]);
            }
        }


        // 计算每个菜的 数据
        $sonPackage = [];
        foreach ($orderDetail as &$detail) {
            // 判断是否有优惠
            if ($allDiscount == 0 && $detail['freeNum'] == 0) {
                $detail['payPrice'] = $detail['originalPrice'];
            }

            $detail['shouldUnitPrice']    = OrderService::calcInter($detail['shopId'],
                $detail['payPrice'] / $detail['num']);
            $detail['orderDiscountPrice'] = $detail['originalPrice'] - $detail['payPrice'];
            $detail['totalDiscountPrice'] = $detail['orderDiscountPrice'];

            // 判断是否是 试吃
            if ($data['payMethod'] == CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK) {
                $detail['orderDiscountPrice'] = 0;
                $detail['totalDiscountPrice'] = $detail['originalPrice'];
                $detail['shouldUnitPrice']    = 0;
                $detail['payPrice']           = 0;
            }

            $detail['packageList'] = self::avgCalcPrice($detail['packageList'], 'packageOriginalPrice', [
                'payPrice'      => $detail['payPrice'],
                'originalPrice' => $detail['originalPrice']
            ]);

            unset($packageOne);
            foreach ($detail['packageList'] as &$packageOne) {
                if ($detail['freeNum'] > 0) {
                    $packageOne['freeNum'] = $packageOne['num'];
                }
                $packageOne['shouldUnitPrice']    = OrderService::calcInter($packageOne['shopId'],
                    $packageOne['payPrice'] / $packageOne['num']);
                $packageOne['originalUnitPrice']  = OrderService::calcInter($packageOne['shopId'],
                    $packageOne['originalPrice'] / $packageOne['num']);
                $packageOne['orderDiscountPrice'] = $packageOne['originalPrice'] - $packageOne['payPrice'];
                $packageOne['totalDiscountPrice'] = $packageOne['orderDiscountPrice'];

                $sonPackage[] = $packageOne;
            }
        }

        $orderDetail = array_merge($orderDetail, $sonPackage);
        return $orderDetail;
    }

    /**
     * 按比例计算金额
     *
     * @param array $data 原始数据
     * @param string $baseKey 基数 key
     * @param array $otherKey 需要计算的 key
     * @param string $resultSortKey 需要用来排序的 key 默认 id
     * @return array
     */
    public static function avgCalcPrice(
        array $data,
        string $baseKey,
        array $otherKey,
        string $resultSortKey = 'id'
    ): array {

        $data = OrderService::arraySort($data, $baseKey, SORT_ASC);

        // 计算总金额
        $sumBaseValue = 0;
        $totalNum     = count($data);

        foreach ($data as $one) {
            $sumBaseValue += $one[$baseKey] ?? 0;
        }
        // 初始化计算 key sum
        $totalOtherKey = [];
        foreach ($otherKey as $k => $ok) {
            $totalOtherKey[$k] = 0;
        }

        // 算平均金额
        $foreachNum = 0;
        foreach ($data as &$one) {
            if ($foreachNum + 1 == $totalNum) {
                foreach ($otherKey as $k => $item) {
                    if (!empty($item['skipDiscount']) && $item['skipDiscount']) {
                        continue;
                    }
                    $one[$k] = $item - $totalOtherKey[$k];
                }
                break;
            }
            $percent = bcdiv($one[$baseKey], $sumBaseValue, 6);

            foreach ($otherKey as $k => $item) {
                if (!empty($item['skipDiscount']) && $item['skipDiscount']) {
                    continue;
                }
                $one[$k]           = OrderService::calcInter($one['shopId'], $percent * $item);
                $totalOtherKey[$k] += $one[$k];
            }
            $foreachNum++;
        }

        $data = OrderService::arraySort($data, $resultSortKey, SORT_ASC);
        return $data;
    }

    /**
     * 格式化 OrderDetail
     *
     * @param $orderDetail
     * @param $order
     * @return array
     */
    public static function formatOfflineOrderDetail($orderDetail, $order, $isPackageSon = false)
    {
        $orderFormatDetail = [
            'id'                       => $orderDetail['id'],
            'orderId'                  => $order['orderId'],
            'brandId'                  => $order['brandId'],
            'shopId'                   => $order['shopId'],
            'productId'                => $orderDetail['productId'],
            'type'                     => $orderDetail['type'] ?? 0,
            'productName'              => $orderDetail['productName'],
            'unit'                     => $orderDetail['unit'],
            'num'                      => $orderDetail['num'],
            'originalPrice'            => $orderDetail['originalPrice'],
            'originalUnitPrice'        => $orderDetail['originalUnitPrice'],
            'packageId'                => $orderDetail['packageId'] ?? 0,
            'packageDetailId'          => $orderDetail['packageDetailId'] ?? 0,
            'packageUnitNum'           => 0,
            'packageUnitOriginalPrice' => 0,
            'packageOriginalPrice'     => 0,
            'shouldUnitPrice'          => 0,
            'payPrice'                 => 0,
            'discountPrice'            => 0, // 单菜打折减免 不收 不处理
            'discountType'             => 0, // 单菜打折减免 不收 不处理
            'discountNum'              => 0, // 单菜打折减免 不收 不处理
            'orderDiscountPrice'       => 0,
            'totalDiscountPrice'       => 0,
            'couponDiscountPrice'      => 0,
            'couponCostPrice'          => 0,
            'freeNum'                  => $orderDetail['freeNum'],
            'refundNum'                => 0, // TODO 不处理退菜数据
            'createdAt'                => $order['createdAt'],
            'createdBy'                => $order['createdBy'],
            'createdByUid'             => $order['createdByUid'],
            'updatedAt'                => $order['createdAt'],
            'updatedBy'                => $order['createdBy'],
            'updatedByUid'             => $order['createdByUid'],
            'menuId'                   => $order['menuId'],
            'imageUrl'                 => str_replace(config('other.IMAGE_URL'), '', $orderDetail['productImageUrl']),
            'categoryId'               => $orderDetail['categoryId'],
            'categoryName'             => self::getCategoryNameById($orderDetail['categoryId'], $order['menuId']),
            'packageList'              => []
        ];

        if ($isPackageSon) {

            $orderFormatDetail['packageUnitNum']           = $orderDetail['num'];
            $orderFormatDetail['num']                      = $order['num'] * $orderDetail['num'];
            $orderFormatDetail['packageOriginalPrice']     = $orderDetail['price'];
            $orderFormatDetail['packageDetailId']          = $order['id'];
            $orderFormatDetail['packageId']                = $order['productId'];
            $orderFormatDetail['packageUnitOriginalPrice'] =
                $orderFormatDetail['packageOriginalPrice'] / $orderFormatDetail['packageUnitNum'];
        }


        return $orderFormatDetail;
    }

    /**
     * 格式化 离线 整单优惠的 数据类型
     *
     * @param $data
     * @return array
     */
    public static function formatOfflineOrderDiscountInputData($data): array
    {
        $orderDiscount = [];

        // 试吃等优惠
        if ($data['payMethod'] == CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK) {
            $orderDiscount[] = [
                'id'              => SnowFlake::nextIdCache(),
                'brandId'         => $data['brandId'],
                'shopId'          => $data['shopId'],
                'orderId'         => $data['orderId'],
                'discountType'    => CodeEnum::ORDER_DISCOUNT_TYPE_CUSTOM_PAY,
                'customPaymentId' => CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK,
                'discountPrice'   => $data['totalPrice']['payPrice'],
                'discountNum'     => 0,
                'createdAt'       => $data['createdAt'],
                'createdByUid'    => $data['createdByUid'],
                'updatedAt'       => $data['createdAt'],
                'updatedByUid'    => $data['createdByUid'],
            ];
        } else {
            // 整单优惠
            if (!empty($data['discount'] && $data['discount']['discountType'] != CodeEnum::ORDER_DISCOUNT_TYPE_NO)) {
                $discount        = $data['discount'];
                $orderDiscount[] = [
                    'id'              => SnowFlake::nextIdCache(),
                    'brandId'         => $data['brandId'],
                    'shopId'          => $data['shopId'],
                    'orderId'         => $data['orderId'],
                    'discountType'    => $discount['discountType'] == CodeEnum::ORDER_DISCOUNT_TYPE_COUNT ?
                        CodeEnum::ORDER_DISCOUNT_TYPE_COUNT : CodeEnum::ORDER_DISCOUNT_TYPE_ANNUL,
                    'customPaymentId' => 0,
                    'discountPrice'   => $discount['discountPrice'],
                    'discountNum'     => $discount['discountNum'],
                    'createdAt'       => $data['createdAt'],
                    'createdByUid'    => $data['createdByUid'],
                    'updatedAt'       => $data['createdAt'],
                    'updatedByUid'    => $data['createdByUid'],
                ];
            }
        }


        return $orderDiscount;
    }

    /**
     * 格式化 离线 自定义支付的 数据类型
     *
     * @param $data
     * @return array
     */
    public static function formatOfflineOrderCustomPaymentInputData($data): array
    {
        $result = [];
        if (in_array($data['payMethod'], [
            CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK,
            CodeEnum::ORDER_PAY_CHANNEL_OFFICE_MONEY,
            CodeEnum::ORDER_PAY_CHANNEL_MONEY
        ])) {
            $result = [
                'shopId'     => $data['shopId'],
                'orderId'    => $data['orderId'],
                'payMoney'   => $data['totalPrice']['payPrice'],
                'payChannel' => $data['payMethod'],
                'reckonType' => PayStreamModel::PAID_IN_YES
            ];

            if ($data['payMethod'] == CodeEnum::ORDER_PAY_CHANNEL_TRY_TACK) {
                $result['reckonType'] = PayStreamModel::PAID_IN_NO;
            }
        }

        return $result;
    }

    /**
     * 处理离线订单的支付入库
     *
     * @param $data
     * @throws \App\Kuafu\Pay\Exceptions\PayException
     */
    public static function handleOfflineOrderCustomPayment($data)
    {
        if ($data['payChannel'] == PayStreamModel::PAY_CHANNEL_CASH) {
            PayService::cashPay(
                $data['shopId'],
                $data['orderId'],
                $data['payMoney']
            );
        } else {

            PayService::customPay(
                $data['shopId'],
                $data['orderId'],
                $data['payMoney'],
                $data['payChannel'],
                $data['reckonType']
            );
        }
    }
}
